package com.helloniu.fl {

/**

----init--------
private var ncHandler:NCHandler = null;
private var sohandler:SOHandler = null;

private function conenct(e:*):void {
    ncHandler = new NCHandler();
    sohandler = new SOHandler();
    ncHandler.setURL("rtmp://localhost/SOSample/12344");
    ncHandler.connect(connectSuccess);
}

private function connectSuccess(handler:NCHandler) {
    sohandler.setName("ppSO");
    sohandler.setNC(handler.getNC());
    sohandler.setStatusListener(statusChange);
    sohandler.connect();
}

function statusChange(asoHandler:SOHandler, pname:String, oldValue:*, newValue:*):void {
    if(pname == null) {
        return;
    }

    newValue = asoHandler.getProperty(pname);

    if(pname == "a") {
        //processAChange(newValue)
    }
    else if(pname == "b") {
        //processBChange(newValue)
    }
}


------set properties-------
sohandler.getSO().setProperty("aaa", "ss");

----close----

sohandler.close();

***/

import flash.events.*;
import flash.net.*;

public class SOHandler {
    public function SOHandler(anetConnection:NetConnection = null, aname:String = null) {
    	setName(aname);
    	setNetConnection(anetConnection);    
    }

    public function setName(aname:String):void {
        this.name = aname;
    }

    public function setNetConnection(anetConnection:NetConnection):void {
        this.netConnection = anetConnection;
    }

    public function setNC(anetConnection:NetConnection):void {
        this.netConnection = anetConnection;
    }

    public function setStatusListener(acallback:Function):void {
        this.callback = acallback;
    }
    
    private var connectedListener:Function = null;
    public function setConnectSuccessListener(acallback:Function):void {
        this.connectedListener = acallback;
    }
    
    private var changeListeners:Array = new Array();
    
    public function addChangeListener(acallback:Function):void {
    	if(changeListeners == null) {
        	changeListeners = new Array();
        }
        
        changeListeners.push(acallback);
    }

    public function getSO():SharedObject {
        return sharedObject;
    }

    public function getSharedObject():SharedObject {
        return sharedObject;
    }

    public function setProperty(pname:String, value:Object = null):void {
        sharedObject.setProperty(pname, value);
    }

    public function send(... arguments):void {
    }

    public function getProperty(propertyName:String):* {
        return sharedObject.data[propertyName];
    }

    public function connect(persistence:Boolean = false):void {
        if(!netConnection.connected) {
            // Show error
            return;
        }

        sharedObject = SharedObject.getRemote(name, netConnection.uri, persistence);
        sharedObject.fps = 10;
        sharedObject.client = this;

        var events:Array = eventsToHandle;
        var n:int = events.length;

        for(var i:int = 0; i < n; i++) {
            sharedObject.addEventListener(events[i], eventHandler, false, 0, false);
        }

        sharedObject.connect(netConnection);
    }

    /**
     *  Strings of the events to listen for.
     */
    private function get eventsToHandle():Array {
        return [ SyncEvent.SYNC, NetStatusEvent.NET_STATUS,
            AsyncErrorEvent.ASYNC_ERROR ];
    }

    /**
     * SharedObject status handler.
     */
    private function eventHandler(event:Event):void {
        var etype:String = event.type;
        var events:Array = eventsToHandle;

        if(etype == events[2]) {
            // trace(async error);
        }
        else if(etype == events[1]) {
            var statusLevel:String = (event as NetStatusEvent).info.level;

            if(statusLevel == "error") {
                // trace(net status error);
                return;
            }

            var statusCode:String = (event as NetStatusEvent).info.code;
            var successCode:String = "NetConnection.Connect.Success";
            var closedCode:String = "NetConnection.Connect.Closed";

            if(statusCode == successCode) {
                //(callback as Function).call(null, this, NCHandler.CONNECTION_SUCCESS, null, null);
            }

            if(statusCode == closedCode) {
                //Alert.show("==SO=close!");
            }

            // trace(connect success);
        }
        else {
            var sevent:SyncEvent = event as SyncEvent;

            // target, currentTarget
            for (var i:int = 0; i < sevent.changeList.length; i++) {
                var changeObj:* = sevent.changeList[i];

                var acode:String = changeObj.code;
                var pname:String = changeObj.name;
                var oval:* = changeObj.oldValue;
                var nval:* = null;

                if(getSO().data.hasOwnProperty(pname)) {
                    nval = getSO().data[pname];
                }
                
                if(acode == "clear" && pname == null) {
                    if(callback != null) {
                        (callback as Function).call(null, this, NCHandler.CONNECTION_SUCCESS, null, null);
                    }
                    
                    connectedListener.call(null, this);
                    return;
                }

                // status listener
                //if("change" == acode) {
                    processOver(pname, oval, nval);
                //}
            }
        }
    }
    
    public function addSyncEventListener():void {
        var events:Array = eventsToHandle;
        sharedObject.addEventListener(events[0], eventHandler, false, 0, false);
    }
    
    public function removeSyncEventListener():void {
        var events:Array = eventsToHandle;
        sharedObject.removeEventListener(events[0], eventHandler);
    }

    public function removeEventListeners():void {
        var events:Array = eventsToHandle;
        var n:int = events.length;

        for(var i:int = 0; i < n; i++) {
            sharedObject.removeEventListener(events[i], eventHandler);
        }
    }

    public function close():void {
        removeEventListeners();

        sharedObject.close();
    }

    private function processOver(pname:String, oval:String, nval:String):void {
        if(callback != null) {
            (callback as Function).call(null, this, pname, oval, nval);
        }
        
        if(changeListeners != null) {
        	var cLength:int = changeListeners.length;
            
        	for(var i:int = 0; i < cLength; i++) {
                (changeListeners[i]as Function).call(null, this, pname, oval, nval);
            }
        }
    }
    
    private var netConnection:NetConnection;
    private var sharedObject:SharedObject;
    private var name:String;
    private var callback:Function;
}
}